//
//  Parser.cpp
//  LightBasic
//
//  Created by Albert on 21/03/2011.
//  Copyright 2011 LightBasic Development Team. All rights reserved.
//

#include "Parser.h"
#include "Context.h"
#include "Lexer.h"
#include "Token.h"
#include "TokenInfo.h"
#include "StringRef.h"
using namespace lbc;


/// Create new parser instance
Parser::Parser(Context & context) : m_context(context), m_lexer(NULL)
{
}


/// Parse files
AstProgram * Parser::Parse()
{
    const ResourceContainer & sources = m_context.GetResources(Context::TypeSource);
    for (ResourceContainer::const_iterator iter = sources.begin(); iter != sources.end(); iter++) {
        Source & file = m_context.GetSource(*iter);
        Lexer lexer(file);
        m_lexer = &lexer;
        
        Move(); Move();
        while(!Match(TknEndOfFile)) {
            const std::string & name = TokenInfo::GetTokenName(m_token->GetType()).str();
            std::string spacer(20 - name.length(), ' ');
            std::cout << name << spacer << "- " << m_token->GetLexeme().str() << '\n';
            delete m_token;
            Move();
        }
        delete m_token;
    }
    
    return NULL;
}


/// Match token
bool Parser::Match(TokenType type) const
{
    return m_token->GetType() == type;
}


/// Accept token of a type and move if matches
bool Parser::Accept(TokenType type)
{
    if (Match(type)) {
        Move();
        return true;
    }
    return false;
}


/// Expect token. Throw an error if doesn't match
void Parser::Expect(TokenType type)
{
    if (!Match(type)) {
        throw Exception("Unexpected token. Found " + m_token->GetLexeme().str() + ". Expected " + TokenInfo::GetTokenName(type).str());
    }
    Move();
}


/// Move to the next token
void Parser::Move()
{
    m_token = m_nextToken;
    m_nextToken = m_lexer->GetNext();
}

